package com.king.armips.android.utils;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.OpenableColumns;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.king.armips.android.base.ActivityLauncher;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class FileUtils {

    private static final Pattern SPECIAL_REGEX_CHARS = Pattern.compile("[*?\\\\|:\"<>]");

    /**
     * 打开系统文件管理器选择文件
     */
    public static void selectFile(ActivityLauncher launcher,ActivityLauncher.OnActivityResult callback){
        selectFile(launcher,"*/*",callback);
    }

    /**
     * 打开系统文件管理器选择文件
     */
    public static void selectFile(ActivityLauncher launcher,String type,ActivityLauncher.OnActivityResult callback) {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType(type);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        launcher.launch(intent,callback);
    }

    /**
     * 保存文件
     */
    public static void saveAs(ActivityLauncher launcher,File file,ActivityLauncher.OnActivityResult callback){
        saveAs(launcher,file,"*/*",callback);
    }

    /**
     * 保存文件
     */
    public static void saveAs(ActivityLauncher launcher,File file,String type,ActivityLauncher.OnActivityResult callback){
        Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
        intent.setType(type);
        intent.putExtra(Intent.EXTRA_TITLE, file.getName());
        launcher.launch(intent,result -> {
            Intent data = result.getData();
            if (data != null){
                Uri uri = data.getData();
                if (uri != null){
                    boolean saved = exportFile(launcher.getContext(), uri, file);
                    if (!saved){
                        callback.onResult(null);
                    }
                }
            }
            callback.onResult(result);
        });
    }

    /**
     * 打开系统文件管理器选择目录
     */
    public static void selectDirectory(ActivityLauncher launcher,ActivityLauncher.OnActivityResult callback) {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
        launcher.launch(intent, callback);
    }

    public static void delete(File file){
        deleteFile(file);
    }

    private static void deleteFile(File dir){
        if (dir == null || !dir.exists())
            return;
        if (dir.isFile()){
            dir.delete();
            return;
        }
        File[] files = dir.listFiles();
        if (files == null || files.length == 0){
            dir.delete();
            return;
        }
        for (File file:files){
            if (file.isDirectory()){
                deleteFile(file);
            }else {
                file.delete();
            }
        }
        dir.delete();
    }

    /**
     * 通过uri保存文件
     */
    public static boolean saveFile(Context context, Uri uri, File dstFile){
        try {
            InputStream inputStream = context.getContentResolver().openInputStream(uri);
            if (inputStream == null)
                return false;
            return saveFile(inputStream, dstFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 保存文件流
     */
    public static boolean saveFile(InputStream inputStream, File dstFile) {
        mkParentDirsIf(dstFile);
        FileOutputStream fos = null;
        boolean saved = false;
        try {
            if (dstFile.exists()){
                boolean delete = dstFile.delete();
                if (!delete) {
                    closeQuietly(inputStream);
                    return false;
                }
            }

            fos = new FileOutputStream(dstFile);
            byte[] buffer = new byte[1024*1024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            saved = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeQuietly(fos,inputStream);
        }
        return saved;
    }

    public static boolean exportFile(Context context, Uri uri, File srcFile){
        OutputStream outputStream = null;
        FileInputStream inputStream = null;
        boolean saved = false;
        try {
            // 获取输出流
            ContentResolver contentResolver = context.getContentResolver();
            outputStream = contentResolver.openOutputStream(uri);

            if (outputStream != null) {
                byte[] buffer = new byte[1024*1024];
                int len;
                inputStream = new FileInputStream(srcFile);
                while ((len = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, len);
                }
            }
            saved = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            closeQuietly(outputStream,inputStream);
        }
        return saved;
    }

    public static String getSuffix(String filename){
        if (filename == null || filename.isEmpty())
            return "";
        int index = filename.lastIndexOf(".");
        if (index == -1)
            return "";
        return filename.substring(index);
    }

    @Nullable
    public static String getFileNameFromUri(Context context,Uri uri){
        String fileName = null;
        ContentResolver contentResolver = context.getContentResolver();

        // 查询文件的相关信息
        Cursor cursor = contentResolver.query(uri, null, null, null, null);
        if (cursor != null && cursor.moveToFirst()) {
            // 获取文件名的列索引
            int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
            if (nameIndex != -1) {
                fileName = cursor.getString(nameIndex);
            }
            cursor.close();
        }

        return fileName;
    }

    public static void writeText(File file,String string){
        if (file == null)
            return;
        if (file.exists()){
            file.delete();
        }
        try(
                FileWriter fileWriter = new FileWriter(file)
        ){
            if (string.isEmpty()){
                fileWriter.write("\n");
            }
            else {
                fileWriter.write(string);
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

    @NonNull
    public static String readText(File file) {
        if (file == null || !file.exists())
            return "";
        StringBuilder builder = new StringBuilder();
        try (
                FileReader fileReader = new FileReader(file);
                BufferedReader bufferedReader = new BufferedReader(fileReader)
        ){
            String line;
            while ((line = bufferedReader.readLine()) != null){
                builder.append(line).append("\n");
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return builder.toString();
    }

    public static void unzipFile(String zipFilePath, String outputDir) {
        File dir = new File(outputDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        try (InputStream fis = new FileInputStream(zipFilePath);
             ZipInputStream zis = new ZipInputStream(fis)
        ) {

            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                File outputFile = new File(outputDir, entry.getName());
                if (entry.isDirectory()) {
                    outputFile.mkdirs();
                } else {
                    try (FileOutputStream fos = new FileOutputStream(outputFile)) {
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = zis.read(buffer)) > 0) {
                            fos.write(buffer, 0, length);
                        }
                    }
                }
                zis.closeEntry();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void unzipAssetFile(Context context,String name,String outputDir){
        try (
                InputStream is = context.getAssets().open(name);
                ZipInputStream zis = new ZipInputStream(is)
        ) {
            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                File outputFile = new File(outputDir, entry.getName());
                if (entry.isDirectory()) {
                    outputFile.mkdirs();
                } else {
                    try (FileOutputStream fos = new FileOutputStream(outputFile)) {
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = zis.read(buffer)) > 0) {
                            fos.write(buffer, 0, length);
                        }
                    }
                }
                zis.closeEntry();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static boolean verifyFilename(File dir,String filename){
        Matcher matcher = SPECIAL_REGEX_CHARS.matcher(filename);
        if (matcher.find())
            return false;

        File file = new File(dir,filename);
        mkParentDirsIf(file);

        return true;
    }

    /**
     * 如果文件夹不存在则创建
     * @param dir 文件夹
     * @return 是否创建成功
     */
    public static boolean mkDirsIf(File dir){
        if (dir == null)
            return false;
        if (dir.exists())
            return true;
        return dir.mkdirs();
    }

    /**
     * 如果父文件夹不存在则创建
     * @param file 文件
     * @return 是否创建成功
     */
    public static boolean mkParentDirsIf(File file){
        if (file == null)
            return false;
        File parentFile = file.getParentFile();
        if (parentFile == null)
            return false;
        if (parentFile.exists())
            return true;
        return parentFile.mkdirs();
    }

    public static void closeQuietly(Closeable... closeables) {
        for (Closeable c:closeables){
            if (c == null)
                continue;
            try {
                c.close();
            } catch (IOException ignored) { }
        }
    }

}
